using System;
using System.Collections.Generic;
using UnityEngine;

namespace UFrame
{
    public class EditorParticlePlayer : TimeObjectManager
    {
        public Transform transform;
        public Transform target;

        public float speed;
        private GameObject go;
        private Action moveOverAction = null;
        private float curTime = 0f;
        private float preUpdateTime = 0f;
        public bool moveOver = false;
        public EPlayType type = EPlayType.Normal;
        public Transform bindBone = null;
        private Vector3 offer = Vector3.zero;
        private Quaternion rotation = Quaternion.identity;
        private List<ParticleSystemTimeControl> particle = new List<ParticleSystemTimeControl>();
        private List<AnimatorTimeControl> animatorParticle = new List<AnimatorTimeControl>();

        public float GetLength()
        {
            float max = 0f;
            foreach (var v in particle)
            {
                max = v.TimeLength > max ? v.TimeLength : max;
            }

            foreach (var v in animatorParticle)
            {
                max = v.TimeLength > max ? v.TimeLength : max;
            }

            return max;
        }

        public void SetLength(float time)
        {
            length = time;
        }

        public void SetParticleGameObject(GameObject go)
        {
            if (this.go != null)
            {
                GameObject.DestroyImmediate(this.go);
            }

            RemoveInvalidAnimator(go.transform);

            this.go = go;
            transform = this.go.transform;
            var animatorList = this.go.GetComponentsInChildren<Animator>(true);
            var particleList = this.go.GetComponentsInChildren<ParticleSystem>(true);

            foreach (ParticleSystemTimeControl pst in particle)
            {
                Remove(pst);
            }

            foreach (var v in animatorParticle)
            {
                Remove(v);
            }

            particle.Clear();
            if (go == null)
            {
                return;
            }

            for (int i = 0; i < particleList.Length; i++)
            {
                ParticleSystemTimeControl pst = new ParticleSystemTimeControl();
                pst.SetObject(particleList[i], null);
                Add(pst);
                particle.Add(pst);
            }

            for (int i = 0; i < animatorList.Length; i++)
            {
                AnimatorTimeControl con = new AnimatorTimeControl();
                con.SetObject(animatorList[i], null);
                Add(con);
                animatorParticle.Add(con);
            }
        }

        public void SetTransform(Transform t)
        {
            if (go != null)
            {
                //Helper.AddChild(t, m_go.transform);
                go.transform.localPosition = Vector3.zero;
                go.transform.localRotation = Quaternion.identity;
                go.transform.localScale = Vector3.one;
            }
        }

        public void SetTransform(Transform t, Vector3 offer, Quaternion rotation, bool isBind, bool isPosition)
        {
            if (isBind)
            {
                if (isPosition)
                {
                    bindBone = t;
                    this.offer = offer;
                    this.rotation = rotation;
                    go.transform.position = t.position + offer;
                    go.transform.rotation = rotation;
                    go.transform.localScale = Vector3.one;
                    type = EPlayType.BindPosition;
                }
                else
                {
                    if (go != null)
                    {
                        //Helper.AddChild(t, m_go.transform);
                        go.transform.localPosition = offer;
                        go.transform.localRotation = Quaternion.identity;
                        go.transform.localScale = Vector3.one;
                        type = EPlayType.Bind;
                    }
                }
            }
            else
            {
                go.transform.localPosition = offer;
                type = EPlayType.Normal;
            }
        }

        public void SetTarget(Transform target, float speed, float startTime, Action OverAction = null)
        {
            this.target = target;
            this.speed = speed;
            preUpdateTime = startTime;
            moveOverAction = OverAction;
            type = EPlayType.Track;
        }

        public void Update(float time)
        {
            switch (type)
            {
                case EPlayType.Track:

                    if (target != null && transform != null)
                    {
                        if (moveOver)
                        {
                            return;
                        }

                        Vector3 v1 = transform.position;
                        //v1.y = 0;
                        Vector3 v2 = target.position;
                        //v2.y = 0;
                        float dis = Vector3.Distance(v1, v2);
                        float offer = time - preUpdateTime;
                        float needTime = dis / speed;
                        float per = offer / needTime;
                        length = needTime;
                        if (per > 1 || per < 0)
                        {
                            go.SetActive(false);
                        }
                        else
                        {
                            go.SetActive(true);
                            Vector3 v = Vector3.Lerp(transform.position, target.position + Vector3.up, per);
                            if (v != Vector3.negativeInfinity)
                            {
                                go.transform.position = v;
                            }
                            else
                            {
                                Debug.Log("");
                            }
                        }

                        // 目标位移
                        target.transform.localPosition = Vector3.zero;


                        preUpdateTime = time;
                    }

                    break;

                case EPlayType.BindPosition:

                    transform.position = bindBone.position + offer;
                    break;
            }
        }

        public void SetOffer(Vector3 offer)
        {
            if (go != null)
            {
                if (type == EPlayType.BindPosition)
                {
                    this.offer = offer;
                }
                else
                {
                    go.transform.localPosition = offer;
                }
            }
        }

        public void SetPos(Vector3 v)
        {
            if (go != null)
            {
                go.transform.position = v;
                go.transform.rotation = Quaternion.identity;
            }
        }

        public override void TimeChange(float time)
        {
            if (go == null)
            {
                return;
            }

            if (time < GetStartTime())
            {
                go.SetActive(false);
                foreach (var v in animatorParticle)
                {
                    v.OnHide(time - startTime);
                }

                foreach (var v in particle)
                {
                    v.OnHide(time - startTime);
                }
            }
            else if (time > GetEndTime())
            {
                go.SetActive(false);
                foreach (var v in animatorParticle)
                {
                    v.OnHide(time - startTime);
                }

                foreach (var v in particle)
                {
                    v.OnHide(time - startTime);
                }
            }
            else
            {
                if (go.activeSelf == false)
                {
                    go.SetActive(true);
                    foreach (var v in animatorParticle)
                    {
                        v.OnShow(time - startTime);
                    }

                    foreach (var v in particle)
                    {
                        v.OnShow(time - startTime);
                    }
                }
            }

            base.TimeChange(time);
        }

        public override void Release()
        {
            base.Release();
            GameObject.DestroyImmediate(go);
            go = null;
        }

        void RemoveInvalidAnimator(Transform parent)
        {
            var animatorList = parent.GetComponentsInChildren<Animator>();

            foreach (var anim in animatorList)
            {
                if (anim.runtimeAnimatorController == null)
                {
                    GameObject.DestroyImmediate(anim);
                }
            }
        }
    }
}